package com.sinog.front.easyexcel.listensr;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sinog.core.domain.PrisonerFx;
import com.sinog.core.domain.PrisonerMain;
import com.sinog.core.domain.PrisonerSr;
import com.sinog.core.domain.PrisonerZn;
import com.sinog.core.model.UserDTO;
import com.sinog.core.util.GkObjectUtils;
import com.sinog.core.util.IdNumUtil;
import com.sinog.core.util.JsonUtil;
import com.sinog.core.utilbean.Constants;
import com.sinog.core.utilbean.Dictionary;
import com.sinog.core.utilbean.Result;
import com.sinog.core.utilbean.ReturnCode;
import com.sinog.front.FrontApplication;
import com.sinog.front.easyexcel.ImportInfo;
import com.sinog.front.feign.basic.UserService;
import com.sinog.front.feign.biz.ExcelImportService;
import com.sinog.front.service.user.UserFacade;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lzq
 * @desc 监听类
 * @date -
 */
@Slf4j
public class ExcelDownloadListener extends AnalysisEventListener<ImportInfo> {

    @Resource
    private ExcelImportService excelImportService;
    @Resource
    private UserService userService;
    @Resource
    private UserFacade userFacade;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    private static final int BATCH_COUNT = 100;
    private final List<ImportInfo> importInfos = new ArrayList<>(16);
    private final AtomicInteger total = new AtomicInteger(0);
    private final AtomicInteger success = new AtomicInteger(0);
    private final AtomicInteger fail = new AtomicInteger(0);
    private String uuid;

    public Integer getTotal() {
        return total.get();
    }

    public Integer getSuccess() {
        return success.get();
    }

    public Integer getFail() {
        return fail.get();
    }

    public ExcelDownloadListener(String uuid) {
        this.uuid = uuid;
    }

    /**
     * 每解析一行会回调invoke()方法。：每隔100条存储数据库，实际使用中可以3000条，然后清理list ，方便内存回收
     * @param data data
     * @param context context
     */
    @Override
    public void invoke(ImportInfo data,AnalysisContext context) {
        log.info("解析到一条数据:{ " + data + " }");
        try {
            boolean allFieldNull1 = GkObjectUtils.isAllFieldNull1(data);
            if(!allFieldNull1) {
                importInfos.add(data);
                total.addAndGet(1);
                //每BATCH_COUNT条入库一次
                if(BATCH_COUNT <= importInfos.size()) {
                    saveData();
                    importInfos.clear();
                }
            }
        } catch(IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 整个excel解析结束会执行doAfterAllAnalysed()方法
     * @param context context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        //确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成！");
    }

    /**
     * 入库 - 调用biz服务接口
     */
    private void saveData() {
        ApplicationContext applicationContext = FrontApplication.applicationContext;
        if(!ObjectUtils.allNotNull(stringRedisTemplate)) {
            stringRedisTemplate = (StringRedisTemplate)applicationContext.getBean("stringRedisTemplate");
        }
        if(!ObjectUtils.allNotNull(userFacade)) {
            userFacade = (UserFacade)applicationContext.getBean("userFacade");
        }
        if(!ObjectUtils.allNotNull(excelImportService)) {
            excelImportService = (ExcelImportService)applicationContext.getBean("com.sinog.front.feign.biz.ExcelImportService");
        }
        if(!ObjectUtils.allNotNull(userService)) {
            userService = (UserService)applicationContext.getBean("com.sinog.front.feign.basic.UserService");
        }
        if(!ObjectUtils.allNotNull(threadPoolTaskExecutor)) {
            threadPoolTaskExecutor = (ThreadPoolTaskExecutor)applicationContext.getBean("taskAsync01-");
        }
        UserDTO userDTO = userFacade.getAuthentication();
        Dictionary singleton = Dictionary.getSingleton();
        CountDownLatch count = new CountDownLatch(importInfos.size());
        for(ImportInfo importInfo : importInfos) {
            threadPoolTaskExecutor.execute(() -> {
                PrisonerMain prisonerMain = new PrisonerMain();
                PrisonerFx prisonerFx = new PrisonerFx();
                PrisonerSr prisonerSr = new PrisonerSr();
                PrisonerZn prisonerZn = new PrisonerZn();
                List<PrisonerSr> prisonerSrs = new ArrayList<>(16);
                List<PrisonerZn> prisonerZns = new ArrayList<>(16);
                //1、主表封装
                prisonerMain.setPName(importInfo.getPname());
                prisonerMain.setUsedName(importInfo.getUsedName());
                Map<String,String> sexMap = singleton.getSexMap();
                if(null != sexMap.get(importInfo.getSex())) {
                    prisonerMain.setSex(sexMap.get(importInfo.getSex()));
                }
                Map<String,String> nationalityMap = singleton.getNationalityMap();
                if(null != nationalityMap.get(importInfo.getNationality())) {
                    prisonerMain.setNationality(nationalityMap.get(importInfo.getNationality()));
                }
                Map<String,String> idtypeMap = singleton.getIdTypeMap();
                if(null != idtypeMap.get(importInfo.getIdType())) {
                    prisonerMain.setIdType(idtypeMap.get(importInfo.getIdType()));
                }
                prisonerMain.setIdNum(importInfo.getIdNum());
                if(!StringUtils.isEmpty(importInfo.getIdType()) && "居民身份证".equals(importInfo.getIdType()) && !StringUtils.isEmpty(importInfo.getIdNum()) && IdNumUtil.checkIdNum(importInfo.getIdNum())) {
                    prisonerMain.setIdNum("");
                }
                prisonerMain.setAge(importInfo.getAge());
                Map<String,String> educationMap = singleton.getEducationMap();
                if(null != educationMap.get(importInfo.getEducation())) {
                    prisonerMain.setEducation(educationMap.get(importInfo.getEducation()));
                }
                prisonerMain.setAddtime(importInfo.getAddtime());
                Map<String,String> priAddrMap = singleton.getPriAddrMap();
                if(null != priAddrMap.get(importInfo.getPriAddr())) {
                    prisonerMain.setPriAddr(priAddrMap.get(importInfo.getPriAddr()));
                }
                //根据excel中的hujidz比对数据库中的地址组合是否存在，存在则设置四层地址，不存在则四层地址置为空
                //这里需要创建一张表，四层中文，省份编码，地市编码，区县编码，街道编码
                //需要根据hujidz查询对应的【省份编码，地市编码，区县编码，街道编码】
                //户籍地址设置
                String hujidz = importInfo.getHujidz();
                if(null == hujidz) {
                    hujidz = "";
                }
                Map allArea = excelImportService.getAllArea(hujidz);
                String sheng = "";
                String shi = "";
                String xian = "";
                String jiedao = "";
                if(Constants.Number.NUM_ZERO < allArea.size()) {
                    sheng = allArea.get("sheng_code").toString();
                    shi = allArea.get("dishi_code").toString();
                    xian = allArea.get("quxian_code").toString();
                    jiedao = allArea.get("jiedao_code").toString();
                } else {
                    //如果根据hujidz不能查询到对应到四层结构，则把prisonerMain四层结构置为空
                    hujidz = "";
                }
                prisonerMain.setNativepro(sheng);
                prisonerMain.setNativecity(shi);
                prisonerMain.setNativecou(xian);
                prisonerMain.setNativevill(jiedao);
                if(null == importInfo.getNativenum()) {
                    importInfo.setNativenum("");
                }
                prisonerMain.setNativenum(importInfo.getNativenum());
                //居住地址设置
                String juzhudz = importInfo.getJuzhudz();
                if(null == juzhudz) {
                    juzhudz = "";
                }
                Map<String,Object> allArea1 = excelImportService.getAllArea(juzhudz);
                log.error("========" + allArea1.toString());
                String shengJz = "";
                String shiJz = "";
                String xianJz = "";
                String jiedaoJz = "";
                if(Constants.Number.NUM_ZERO < allArea1.size()) {
                    shengJz = allArea1.get("sheng_code").toString();
                    shiJz = allArea1.get("dishi_code").toString();
                    xianJz = allArea1.get("quxian_code").toString();
                    jiedaoJz = allArea1.get("jiedao_code").toString();
                    log.error(shengJz);
                    log.error(shiJz);
                    log.error(xianJz);
                    log.error(jiedaoJz);
                } else {
                    //如果根据juzhudz不能查询到对应到四层结构，则把prisonerMain四层结构置为空
                    juzhudz = "";
                }
                prisonerMain.setPlacepro(shengJz);
                prisonerMain.setPlacecity(shiJz);
                prisonerMain.setPlacecou(xianJz);
                prisonerMain.setPlacevill(jiedaoJz);
                if(null == importInfo.getPlacenum()) {
                    importInfo.setPlacenum("");
                }
                prisonerMain.setPlacenum(juzhudz + importInfo.getPlacenum());
                //从redis里面取
                //2、服刑表封装
                if(Boolean.TRUE.equals(stringRedisTemplate.hasKey("critypeZn"))) {
                    String critypesFinal = null;
                    if(!StringUtils.isEmpty(importInfo.getCritype())) {
                        String[] critypes = importInfo.getCritype().split(",");
                        List<String> critypesLists = new ArrayList<>(16);
                        for(String c : critypes) {
                            //根据罪名查询对应的犯罪类型
                            String critypeCode = (String)stringRedisTemplate.opsForHash().get("critypeZn",c);
                            if(!critypesLists.contains(critypeCode)) {
                                critypesLists.add(critypeCode);
                            }
                        }
                        String temp = null;
                        for(String f : critypesLists) {
                            if(!StringUtils.isEmpty(temp)) {
                                temp = new StringBuilder(16).append(temp).append(",").append(f).toString();
                            } else {
                                temp = f;
                            }
                        }
                        critypesFinal = temp;
                    }
                    if(StringUtils.isEmpty(critypesFinal)) {
                        prisonerFx.setCritype(null);
                    } else {
                        prisonerFx.setCritype(critypesFinal);
                    }
                }
                Map<String,String> precriMap = singleton.getPrecriMap();
                if(null != precriMap.get(importInfo.getPrecri())) {
                    prisonerFx.setPrecri(precriMap.get(importInfo.getPrecri()));
                }
                Map<String,String> addpenaltyMap = singleton.getAddpenaltyMap();
                if(null != addpenaltyMap.get(importInfo.getAddpenalty())) {
                    prisonerFx.setAddpenalty(addpenaltyMap.get(importInfo.getAddpenalty()));
                }
                Map<String,String> jinengMap = singleton.getJinengtypeMap();
                if(null != jinengMap.get(importInfo.getJinengtype())) {
                    prisonerFx.setJinengtype(jinengMap.get(importInfo.getJinengtype()));
                }
                Map<String,String> pritimeMap = singleton.getPritimeMap();
                if(null != pritimeMap.get(importInfo.getPritime())) {
                    prisonerFx.setPritime(pritimeMap.get(importInfo.getPritime()));
                }
                prisonerFx.setArrJg(importInfo.getArrJg());
                prisonerFx.setPriBegin(importInfo.getPriBegin());
                prisonerFx.setPriStop(importInfo.getPriStop());
                Map<String,String> aftypeMap = singleton.getAftypeMap();
                if(null != aftypeMap.get(importInfo.getAftype())) {
                    prisonerFx.setAftype(aftypeMap.get(importInfo.getAftype()));
                }
                //从redis里面取
                if(Boolean.TRUE.equals(stringRedisTemplate.hasKey("bqzyZn"))) {
                    if(null == importInfo.getBqzy()) {
                        importInfo.setBqzy("");
                    }
                    String bqzyCode = (String)stringRedisTemplate.opsForHash().get("bqzyZn",importInfo.getBqzy());
                    if(StringUtils.isEmpty(bqzyCode)) {
                        prisonerFx.setBqzy("");
                    } else {
                        prisonerFx.setBqzy(bqzyCode);
                    }
                }
                Map<String,String> bqzyMap = singleton.getBqzyMap();
                if(null != bqzyMap.get(importInfo.getBqzy())) {
                    prisonerFx.setBqzy(bqzyMap.get(importInfo.getBqzy()));
                }
                //根据罪名设置犯罪类型
                String fzlx = null;
                if(!StringUtils.isEmpty(prisonerFx.getCritype())) {
                    String[] critypes = prisonerFx.getCritype().split(",");
                    List<String> fzlxs = new ArrayList<>(16);
                    for(String c : critypes) {
                        //根据罪名查询对应的犯罪类型
                        String fzlxTemp = (String)stringRedisTemplate.opsForHash().get("critypeAndFzlx",c);
                        if(StringUtils.isBlank(fzlxTemp)) {
                            fzlxTemp = c;
                        }
                        if(!fzlxs.contains(fzlxTemp)) {
                            fzlxs.add(fzlxTemp);
                        }
                    }
                    String temp = null;
                    for(String f : fzlxs) {
                        if(!StringUtils.isEmpty(temp)) {
                            temp = new StringBuilder(16).append(temp).append(",").append(f).toString();
                        } else {
                            temp = f;
                        }
                    }
                    fzlx = temp;
                }
                prisonerFx.setFzlx(fzlx);
                Map<String,String> canjiMap = singleton.getCanjiMap();
                if(null != canjiMap.get(importInfo.getCanji())) {
                    prisonerFx.setCanji(canjiMap.get(importInfo.getCanji()));
                }
                //3、封装社会关系表
                prisonerSr.setThename(importInfo.getThename());
                Map<String,String> relationMap = singleton.getRelationMap();
                if(null != relationMap.get(importInfo.getRelation())) {
                    prisonerSr.setRelation(relationMap.get(importInfo.getRelation()));
                }
                Map<String,String> srIdTypeMap = singleton.getIdTypeMap();
                if(null != srIdTypeMap.get(importInfo.getSrIdtype())) {
                    prisonerSr.setIdType(srIdTypeMap.get(importInfo.getSrIdtype()));
                }
                prisonerSr.setIdnumber(importInfo.getIdnumber());
                boolean flag = !StringUtils.isEmpty(importInfo.getIdnumber()) && (Constants.NumberStr.NUM_STR_ZERO_ONE.equals(importInfo.getSrIdtype()) || Constants.NumberStr.NUM_STR_ZERO_TWO.equals(importInfo.getSrIdtype())) && IdNumUtil.checkIdNum(importInfo.getIdnumber());
                if(flag) {
                    prisonerSr.setIdnumber("");
                }
                Map<String,String> genderMap = singleton.getSexMap();
                if(null != genderMap.get(importInfo.getGender())) {
                    prisonerSr.setGender(genderMap.get(importInfo.getGender()));
                }
                prisonerSr.setAge(importInfo.getSrAge());
                prisonerSr.setDanwei(importInfo.getDanwei());
                prisonerSr.setTel(importInfo.getTel());
                prisonerSr.setMobile(importInfo.getMobile());
                //家庭地址设置
                String jtdz = importInfo.getJtdz();
                if(null == jtdz) {
                    jtdz = "";
                }
                //如果根据jtdz能查询到对应到四层结构，则取出四层结构分别设置到shengJt、shiJt、xianJt、jiedaoJt
                Map<String,Object> allArea2 = excelImportService.getAllArea(jtdz);
                String shengJt = "";
                String shiJt = "";
                String xianJt = "";
                String jiedaoJt = "";
                if(Constants.Number.NUM_ZERO < allArea2.size()) {
                    shengJt = allArea2.get("sheng_code").toString();
                    shiJt = allArea2.get("dishi_code").toString();
                    xianJt = allArea2.get("quxian_code").toString();
                    jiedaoJt = allArea2.get("jiedao_code").toString();
                } else {
                    //如果根据jtdz不能查询到对应到四层结构，则把prisonerMain四层结构置为空
                    jtdz = "";
                }
                prisonerSr.setAddrpro(shengJt);
                prisonerSr.setAddrcity(shiJt);
                prisonerSr.setAddrcou(xianJt);
                prisonerSr.setAddrvil(jiedaoJt);
                if(null == importInfo.getAddrdetail()) {
                    importInfo.setAddrdetail("");
                }
                prisonerSr.setAddrdetail(jtdz + importInfo.getAddrdetail());
                try {
                    boolean psa = !GkObjectUtils.isAllFieldNull1(prisonerSr);
                    if(psa) {
                        prisonerSrs.add(prisonerSr);
                    }
                } catch(IllegalAccessException e) {
                    log.error("发生异常:",e);
                }
                //4、封装子女表
                prisonerZn.setName(importInfo.getName());
                if(null != sexMap.get(importInfo.getZnSex())) {
                    prisonerZn.setSex(sexMap.get(importInfo.getZnSex()));
                }
                Map<String,String> znIdType = singleton.getIdTypeMap();
                if(null != znIdType.get(importInfo.getZnIdType())) {
                    prisonerZn.setIdType(znIdType.get(importInfo.getZnIdType()));
                }
                prisonerZn.setZnsfId(importInfo.getZnsfId());
                boolean flag2 = !StringUtils.isEmpty(importInfo.getZnsfId()) && (Constants.NumberStr.NUM_STR_ZERO_ONE.equals(importInfo.getZnIdType()) || Constants.NumberStr.NUM_STR_ZERO_TWO.equals(importInfo.getZnIdType())) && IdNumUtil.checkIdNum(importInfo.getZnsfId());
                if(flag2) {
                    prisonerZn.setZnsfId("");
                }
                prisonerZn.setAge(importInfo.getZnAge());
                Map<String,String> jianhurenMap = singleton.getJianhurenMap();
                if(null != jianhurenMap.get(importInfo.getJianhuren())) {
                    prisonerZn.setJianhuren(jianhurenMap.get(importInfo.getJianhuren()));
                }
                Map<String,String> kunnanMap = singleton.getKunnanMap();
                if(null != kunnanMap.get(importInfo.getKunnan())) {
                    prisonerZn.setKunnan(kunnanMap.get(importInfo.getKunnan()));
                }
                Map<String,String> shixueMap = singleton.getShixueMap();
                if(null != shixueMap.get(importInfo.getShixue())) {
                    prisonerZn.setShixue(shixueMap.get(importInfo.getShixue()));
                }
                Map<String,String> liulangMap = singleton.getLiulangMap();
                if(null != liulangMap.get(importInfo.getLiulang())) {
                    prisonerZn.setLiulang(liulangMap.get(importInfo.getLiulang()));
                }
                Map<String,String> fanzuiMap = singleton.getFanzuiMap();
                if(null != fanzuiMap.get(importInfo.getFanzui())) {
                    prisonerZn.setFanzui(fanzuiMap.get(importInfo.getFanzui()));
                }
                //户籍地设置
                String hujid = importInfo.getHujid();
                if(null == hujid) {
                    hujid = "";
                }
                //如果根据hujid能查询到对应到四层结构，则取出四层结构分别设置到shengHjd、shiHjd、xianHjd、jiedaoHjd
                Map<String,Object> allArea3 = excelImportService.getAllArea(hujid);
                String shengHjd = "";
                String shiHjd = "";
                String xianHjd = "";
                String jiedaoHjd = "";
                if(Constants.Number.NUM_ZERO < allArea3.size()) {
                    shengHjd = allArea3.get("sheng_code").toString();
                    shiHjd = allArea3.get("dishi_code").toString();
                    xianHjd = allArea3.get("quxian_code").toString();
                    jiedaoHjd = allArea3.get("jiedao_code").toString();
                } else {
                    //如果根据jtdz不能查询到对应到四层结构，则把prisonerMain四层结构置为空
                    hujid = "";
                }
                prisonerZn.setNativepro(shengHjd);
                prisonerZn.setNativecity(shiHjd);
                prisonerZn.setNativecou(xianHjd);
                prisonerZn.setNativevill(jiedaoHjd);
                if(null == importInfo.getZnNativenum()) {
                    importInfo.setZnNativenum("");
                }
                prisonerZn.setNativenum(hujid + importInfo.getZnNativenum());
                //居住地设置
                String juzhud = importInfo.getJuzhud();
                if(null == juzhud) {
                    juzhud = "";
                }
                //如果根据juzhud能查询到对应到四层结构，则取出四层结构分别设置到shengJzd、shiJzd、xianJzd、jiedaoJzd
                Map<String,Object> allArea4 = excelImportService.getAllArea(juzhud);
                String shengJzd = "";
                String shiJzd = "";
                String xianJzd = "";
                String jiedaoJzd = "";
                if(Constants.Number.NUM_ZERO < allArea4.size()) {
                    shengJzd = allArea4.get("sheng_code").toString();
                    shiJzd = allArea4.get("dishi_code").toString();
                    xianJzd = allArea4.get("quxian_code").toString();
                    jiedaoJzd = allArea4.get("jiedao_code").toString();
                } else {
                    //如果根据jtdz不能查询到对应到四层结构，则把prisonerMain四层结构置为空
                    juzhud = "";
                }
                prisonerZn.setPlacepro(shengJzd);
                prisonerZn.setPlacecity(shiJzd);
                prisonerZn.setPlacecou(xianJzd);
                prisonerZn.setPlacevill(jiedaoJzd);
                if(null == importInfo.getZnPlacenum()) {
                    importInfo.setZnPlacenum("");
                }
                prisonerZn.setPlacenum(juzhud + importInfo.getZnPlacenum());
                try {
                    boolean pza = !GkObjectUtils.isAllFieldNull1(prisonerZn);
                    if(pza) {
                        prisonerZns.add(prisonerZn);
                    }
                } catch(IllegalAccessException e) {
                    log.error("发生异常:",e);
                }
                String s = JsonUtil.toText(userDTO);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("PrisonerMainExcelTemp",prisonerMain);
                log.error(prisonerMain.getNativepro());
                jsonObject.put("PrisonerFxExcelTemp",prisonerFx);
                jsonObject.put("PrisonerSrExcelTemp",prisonerSrs);
                jsonObject.put("PrisonerZnExcelTemp",prisonerZns);
                jsonObject.put("user",s);
                jsonObject.put("uuid",uuid);
                String jsonString = JSON.toJSONStringWithDateFormat(jsonObject,JSON.DEFFAULT_DATE_FORMAT);
                //保存数据到临时表
                Result result = excelImportService.savePreArrangedPersonnelExcelTemp(jsonString);
                if(ReturnCode.FAILURE.code().equals(result.getCode())) {
                    log.info("校验失败！");
                    fail.addAndGet(Constants.Number.NUM_ONE);
                } else if(ReturnCode.SUCCESS.code().equals(result.getCode())) {
                    log.info("校验成功！");
                    success.addAndGet(Constants.Number.NUM_ONE);
                }
                count.countDown();
            });
        }
        try {
            count.await();
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
        log.info(">>>>>>>>>>本次导入excel结束<<<<<<<<<<");
    }
}